﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.IO.IsolatedStorage;
using System.Windows.Navigation;
using System.Device.Location;
using System.Windows.Threading;
using Microsoft.Phone.Net.NetworkInformation;
using System.Text;
using System.IO;
using Microsoft.Phone.Scheduler;
using Microsoft.Phone.Shell;
using Microsoft.Phone.Notification;
using System.Windows.Media.Imaging;
using System.Diagnostics;

namespace NearChat
{
    public enum BatchingInterval
    {
        TileImmediately = 1,
        ToastImmediately = 2,
        RawImmediately = 3,
        TileWait450 = 11,
        ToastWait450 = 12,
        RawWait450 = 13,
        TileWait900 = 21,
        ToastWait900 = 22,
        RawWait900 = 23
    }

    public partial class MainPage : PhoneApplicationPage
    {
        //storage dell'applicazione
        private static IsolatedStorageSettings appSettings = IsolatedStorageSettings.ApplicationSettings;

        //timer refresh
        private static DispatcherTimer myTimer;

        //canale della notifica
        private static HttpNotificationChannel httpChannel;
        private static string channelName = "NearChatChannel";
        private static Uri channelUri;

        //background agent
        private PeriodicTask periodicTask;
        private string periodicTaskName = "NearChatGPSPeriodicTask";

        //classe per la geo-localizzazione
        private static GeoCoordinateWatcher watcher;

        private string user;
        private string IDuser;
        private double lat;
        private double lon;

        // Constructor
        public MainPage()
        {
            InitializeComponent();

            //nascondo il numero di nuovi messaggi, aspetto il timer
            NuoviMessaggiBorder.Visibility = System.Windows.Visibility.Collapsed;

            try
            {
                //rimuovo tutto
                foreach (PeriodicTask oldTask in ScheduledActionService.GetActions<PeriodicTask>())
                {
                    ScheduledActionService.Remove(oldTask.Name);
                }

                // Creo il task
                periodicTask = new PeriodicTask(periodicTaskName);
                periodicTask.Description = "GPS Update";

                // Schedulo il task
                ScheduledActionService.Add(periodicTask);
                //ScheduledActionService.LaunchForTest(periodicTaskName,TimeSpan.FromSeconds(60)); only for test
            }
            catch (InvalidOperationException exception)
            {
                MessageBox.Show("an unknow error as accured: " + exception.ToString());
            }

        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (!(appSettings.Contains("ID")))//non c'è un account
            {
                NavigationService.Navigate(new Uri("/Login.xaml", UriKind.Relative));//cambio della pagina
            }
        }

        private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
        {
            user = appSettings["user"].ToString();
            IDuser = appSettings["ID"].ToString();
            channelUri = (Uri)appSettings["uri"];

            Saluto.Text = "Benvenuto "+user+"!";

            if (NavigationService.CanGoBack)//ho appena fatto il login
                NavigationService.RemoveBackEntry();

            //watcher GPS
            watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
            watcher.Start();

            //creazione e settaggio timer
            myTimer = new System.Windows.Threading.DispatcherTimer();
            myTimer.Interval = new TimeSpan(0, 0, 5);//ongi 5 secondi
            myTimer.Tick += new EventHandler(Timer_Tick);
            myTimer.Start();

            //prelevo il canale
            httpChannel = HttpNotificationChannel.Find(channelName);

            if (httpChannel == null)//canale non presente
            {
                httpChannel = new HttpNotificationChannel(channelName);//creo il canale

                //creo eventi utili e assegno
                httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(httpChannel_ChannelUriUpdated);

                httpChannel.Open();//apro il canale
                //httpChannel.BindToShellTile();
                httpChannel.BindToShellToast();
            }
            else
            {
                //riassegno eventi utili
                httpChannel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(httpChannel_ChannelUriUpdated);

                channelUri = httpChannel.ChannelUri;
            }

            //salvo l'uri in locale
            if (appSettings.Contains("uri"))
            {   
                if (NetworkInterface.GetIsNetworkAvailable())//aggiorno dato sul server
                {
                    //faccio request PHP al DB
                    Uri myDBuri = new Uri("http://www.nearchat.altervista.org/updateUri.php");
                    HttpWebRequest uriRequest = (HttpWebRequest)HttpWebRequest.Create(myDBuri);
                    uriRequest.Method = "POST";
                    uriRequest.ContentType = "application/x-www-form-urlencoded";
                    uriRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallbackUri), uriRequest);
                }
                else
                    MessageBox.Show("connection error, please retry later.");      
            }
            else 
            {
                appSettings.Add("uri", channelUri);//lo creo
                
                if (NetworkInterface.GetIsNetworkAvailable())//lo inserisco nel server
                {
                    //faccio request PHP al DB
                    Uri myDBuri = new Uri("http://www.nearchat.altervista.org/updateUri.php");
                    HttpWebRequest uriRequest = (HttpWebRequest)HttpWebRequest.Create(myDBuri);
                    uriRequest.Method = "POST";
                    uriRequest.ContentType = "application/x-www-form-urlencoded";
                    uriRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallbackUri), uriRequest);
                }
                else
                    MessageBox.Show("connection error, please retry later.");
            }

            watcher.Start();
            GeoCoordinate co = watcher.Position.Location;

            lat = co.Latitude;
            lon = co.Longitude;

            //controllo dati
            if (!(double.IsNaN(lat) || double.IsNaN(lon)))//sono leggibili
            {
                //salvo i dati in locale, già pronti per il DB
                if (appSettings.Contains("lat"))
                {
                    appSettings["lat"] = lat.ToString().Replace(',', '.');
                    appSettings["lon"] = lon.ToString().Replace(',', '.');
                }
                else
                {
                    appSettings.Add("lat", lat.ToString().Replace(',', '.'));
                    appSettings.Add("lon", lon.ToString().Replace(',', '.'));
                }

                NuoviMessaggiText_Loaded(NuoviMessaggiText, new RoutedEventArgs());
            }
            else //se uno dei due è inleggibile
                MessageBox.Show("impossible get your GPS position, please retry later.");
        }//PhoneApplicationPage_Loaded

        void GetRequestStreamCallbackUri(IAsyncResult callbackResult)
        {
            HttpWebRequest myRequest = (HttpWebRequest)callbackResult.AsyncState;
            // End the stream request operation
            Stream postStream = myRequest.EndGetRequestStream(callbackResult);

            // Create the post data
            string postData = "apikey=4nn!eSupp0rt&user=" + IDuser+"&uri="+channelUri;
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);

            // Add the post data to the web request
            postStream.Write(byteArray, 0, byteArray.Length);
            postStream.Close();

            // Start the web request
            myRequest.BeginGetResponse(new AsyncCallback(GetResponsetStreamCallbackUri), myRequest);
        }//GetRequestStreamCallbackUri

        void GetResponsetStreamCallbackUri(IAsyncResult callbackResult)
        {
            HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
            using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream()))
            {
                string result = httpWebStreamReader.ReadToEnd();
                Dispatcher.BeginInvoke(() => ParsingUri(result));
            }
        }//GetResponsetStreamCallbackUri

        void ParsingUri(string result)
        {
            if (result != "")//avvenuto errore
            {
                string[] ris = majorSplit(result);
                ris = minorSplit(ris[0]);//sono sicuro che è uno solo

                if (ris[0] == "ERRORE")
                    MessageBox.Show(ris[1]);//stampo l'errore
                else
                {
                    appSettings["uri"] = channelUri;
                
                }
            }
        }//ParsingUpdateUri

        private void ButtonProfilo_Tap(object sender, GestureEventArgs e)
        {
            myTimer.Stop();
            NavigationService.Navigate(new Uri("/Profilo.xaml?ID="+IDuser, UriKind.Relative));//cambio della pagina
        }

        private void buttonCerca_Tap(object sender, GestureEventArgs e)
        {
            myTimer.Stop();
            NavigationService.Navigate(new Uri("/Cerca.xaml?funct=cerca", UriKind.Relative));//cambio della pagina
        }

        private void buttonPreferiti_Tap(object sender, GestureEventArgs e)
        {
            myTimer.Stop();
            NavigationService.Navigate(new Uri("/Cerca.xaml?funct=preferiti", UriKind.Relative));//cambio della pagina
        }

        private void buttonRic_Tap(object sender, GestureEventArgs e)
        {
            myTimer.Stop();
            NavigationService.Navigate(new Uri("/Riconoscimenti.xaml", UriKind.Relative));//cambio della pagina
        }

        private void buttonInfo_Tap(object sender, GestureEventArgs e)
        {
            myTimer.Stop();
            NavigationService.Navigate(new Uri("/Info.xaml", UriKind.Relative));//cambio della pagina
        }

        private void buttonLogout_Tap(object sender, GestureEventArgs e)
        {
            myTimer.Stop();
            NavigationService.Navigate(new Uri("/Logout.xaml", UriKind.Relative));//cambio della pagina
        }

        private void buttonNera_Tap(object sender, GestureEventArgs e)
        {
            myTimer.Stop();
            NavigationService.Navigate(new Uri("/Cerca.xaml?funct=bloccati", UriKind.Relative));//cambio della pagina
        }

        //splitta la stringa passata in base a |
        private string[] minorSplit(string result)
        {
            return result.Split('|');
        }

        //splitta la stringa passata in base a §
        private string[] majorSplit(string result)
        {
            return result.Split('§');
        }

        void Timer_Tick(object sender, object e)
        {
            watcher.Start();
            GeoCoordinate co = watcher.Position.Location;

            lat = co.Latitude;
            lon = co.Longitude;

            //controllo dati
            if (!(double.IsNaN(lat) || double.IsNaN(lon)))//sono leggibili
            {
                //salvo i dati in locale, già pronti per il DB
                if (appSettings.Contains("lat"))
                {
                    appSettings["lat"] = lat.ToString().Replace(',', '.');
                    appSettings["lon"] = lon.ToString().Replace(',', '.');
                }
                else
                {
                    appSettings.Add("lat", lat.ToString().Replace(',', '.'));
                    appSettings.Add("lon", lon.ToString().Replace(',', '.'));
                }

                if (NetworkInterface.GetIsNetworkAvailable())
                {
                    //faccio request PHP al DB
                    Uri myDBuri = new Uri("http://www.nearchat.altervista.org/nuoviMessaggi.php");
                    HttpWebRequest newRequest = (HttpWebRequest)HttpWebRequest.Create(myDBuri);
                    newRequest.Method = "POST";
                    newRequest.ContentType = "application/x-www-form-urlencoded";
                    newRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallbackNuovi), newRequest);
                }
                else
                    MessageBox.Show("connection error, please retry later.");
            }
            else //se uno dei due è inleggibile
                MessageBox.Show("impossible get your GPS position, please retry later.");    
        }

        void GetRequestStreamCallbackNuovi(IAsyncResult callbackResult)
        {
            HttpWebRequest myRequest = (HttpWebRequest)callbackResult.AsyncState;
            // End the stream request operation
            Stream postStream = myRequest.EndGetRequestStream(callbackResult);

            // Create the post data
            string postData = "apikey=4nn!eSupp0rt&user=" + IDuser + "&lat=" + lat.ToString().Replace(',', '.') + "&lon=" + lon.ToString().Replace(',', '.');
            byte[] byteArray = Encoding.UTF8.GetBytes(postData);

            // Add the post data to the web request
            postStream.Write(byteArray, 0, byteArray.Length);
            postStream.Close();

            // Start the web request
            myRequest.BeginGetResponse(new AsyncCallback(GetResponsetStreamCallbackNuovi), myRequest);
        }//GetRequestStreamCallbackNuovi

        void GetResponsetStreamCallbackNuovi(IAsyncResult callbackResult)
        {
            HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
            using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream()))
            {
                string result = httpWebStreamReader.ReadToEnd();
                Dispatcher.BeginInvoke(() => ParsingNuovi(result));
            }
        }//GetResponsetStreamCallbackNuovi

        void ParsingNuovi(string result)
        {
            if (result != "")
            {
                string[] ris = majorSplit(result);
                ris = minorSplit(ris[0]);//sono sicuro che è uno solo

                if (ris[0] == "ERRORE")
                    MessageBox.Show(ris[1]);//stampo l'errore
                else
                {
                    if (ris[1] != "0" && ris[1]!="")//ci sono messaggi
                    {
                        NuoviMessaggiText.Text = ris[1];
                        NuoviMessaggiBorder.Visibility = System.Windows.Visibility.Visible;
                    }
                    else
                    {
                        NuoviMessaggiText.Text = ris[1];
                        NuoviMessaggiBorder.Visibility = System.Windows.Visibility.Collapsed;
                    }
                }
            }
            else //==""
            {
                NuoviMessaggiText.Text = "";
                NuoviMessaggiBorder.Visibility = System.Windows.Visibility.Collapsed;
            }
        }//ParsingUpdateNuovi

        void httpChannel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
        {
            channelUri = e.ChannelUri;

            if(appSettings.Contains("uri"))
            {
                appSettings["uri"]=channelUri;
            }
            else
            {
                appSettings.Add("uri",channelUri);
            }

            Dispatcher.BeginInvoke(() => MessageBox.Show("ChannelUriUpdated"));
        }//Channel_ChannelUriUpdated

        void httpChannel_HttpNotificationReceived(object sender, HttpNotificationEventArgs e)
        {
            Dispatcher.BeginInvoke(() => MessageBox.Show("ErrorOccurred"));
        }//httpChannel_HttpNotificationReceived

        void httpChannel_ShellToastNotificationReceived(object sender, NotificationEventArgs e)
        {

        }//Channel_ShellToastNotificationReceived


        void httpChannel_ErrorOccurred(object sender, NotificationChannelErrorEventArgs e)
        {

        }//httpChannel_ErrorOccurred

        private void NuoviMessaggiText_Loaded(object sender, RoutedEventArgs e)
        {
            if (NetworkInterface.GetIsNetworkAvailable())
            {
                //faccio request PHP al DB
                Uri myDBuri = new Uri("http://www.nearchat.altervista.org/nuoviMessaggi.php");
                HttpWebRequest newRequest = (HttpWebRequest)HttpWebRequest.Create(myDBuri);
                newRequest.Method = "POST";
                newRequest.ContentType = "application/x-www-form-urlencoded";
                newRequest.BeginGetRequestStream(new AsyncCallback(GetRequestStreamCallbackNuovi), newRequest);
            }
            else
                MessageBox.Show("connection error, please retry later.");
        }//NuoviMessaggiText_Loaded


    }
}